/*
 * @文件描述:初始化系统，初始化各个线程，线程的管理
 * @版本:
 * @作者: 周晨阳
 * @Date: 2021-01-13 21:43:10
 * test1 from laptop,
 * test2 from laptop.
 */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
//#include "GUI.h"
#include "LED.h"
#include "TFT.h"
#include "usart.h"
#include <rtthread.h>
#include "myADC.h"
//#include "OscilloscopeUICodes.h"
#include "mySRAM.h"
#include "myButton.h"
#include "OscilloscopePre.h"
#include "multiMeter.h"
#include "MultiMeterPre.h"
#include "oscilloscope.h"
#include "beeper.h"
#include "sigGenerator.h"
#include "filter.h"
#include "homePage.h"
#include "HomePagePre.h"
#include "myFlash.h"
#include "ff.h"
#include "exfuns.h"
#include "delay.h"
#include "fontupd.h"
#include "fattester.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/

static struct rt_thread LEDThread_ptr;
static rt_uint8_t LEDThread_stack[400];

static struct rt_thread TFTThread_ptr;
static rt_uint8_t TFTThread_stack[3000];

static struct rt_thread touchScreenThread_ptr;
static rt_uint8_t touchScreenThread_stack[60];

static struct rt_thread systestThread_ptr;
static rt_uint8_t systestThread_stack[100];

static struct rt_thread buttonThread_ptr;
static rt_uint8_t buttonThread_stack[80];

static struct rt_thread oscillThread_ptr;
static rt_uint8_t oscillThread_stack[60];

static struct rt_thread multiMeterThread_ptr;
static rt_uint8_t multiMeterThread_stack[12];

static struct rt_mutex lvglMutex;
static int Fps = 0;
static uint8_t touchFreashRate = 0;

/* Private function prototypes -----------------------------------------------*/

/* Private functions ---------------------------------------------------------*/
/**
 * @brief : 打印线程的状态
 * @param {struct rt_thread} thread
 * @return {*}
 */
void printThreadState(struct rt_thread thread)
{
  printf("thread:%s, state:%d\n", thread.name, thread.stat);
}
/**
 * @brief : 打印所有线程的状态
 * @param {*}
 * @return {*}
 */
void printfAllThreadStat()
{
  printThreadState(oscillThread_ptr);
  printThreadState(touchScreenThread_ptr);
  printThreadState(buttonThread_ptr);
  printThreadState(multiMeterThread_ptr);
  printThreadState(TFTThread_ptr);
}
/**
 * @description: 实体按键扫描线程
 * @param {void} *parameter
 * @return {*}
 */
void buttonThread(void *parameter)
{
  while (1)
  {

    buttonLooper();
    //printf("button thread running\n");
    rt_thread_mdelay(40);
  }
}
/**
 * @brief : 触摸屏扫描线程
 * @param {void} *parameter
 * @return {*}
 */
void touchScreenThread(void *parameter)
{
  while (1)
  {
#ifdef GUI_UCGUI
    GUI_TOUCH_Exec(); //调用UCGUI TOUCH相关函数
#endif

    //printf("touch thread running\n");
    touchFreashRate++;
    rt_thread_mdelay(20);
  }
}
/**
 * @brief tft刷新线程
 * @param {void} *parameter
 * @return {*}
 */
void tftUpdateThread(void *parameter)
{
  int i;
  while (1)
  {
    // if (getCurrentApp() == APP_OSCILL)
    // {
    //   //V_drawOscilGraph();
    // }
    // else if (getCurrentApp() == APP_MULTIMETER)
    // {
    //   //V_drawNiddle();
    // }
#ifdef GUI_UCGUI
    GUI_Exec(); //调用UCGUI
#endif

#ifdef GUI_LVGL
    rt_mutex_take(&lvglMutex, 10);
    lv_timer_handler();
    rt_mutex_release(&lvglMutex);

#endif
    Fps++;
    // printf("tft thread running\n");
    rt_thread_mdelay(10);
  }
}
/**
 * @brief : 系统初始化线程，用于设置一些东西
 * @param {void} *p
 * @return {*}
 */
void sysStartUpThread(void *p)
{
  rt_thread_mdelay(1000);
}
/**
 * @brief : 示波器线程
 * @param {void} *p
 * @return {*}
 */
void oscillThread(void *p)
{
  while (1)
  {
    /* code */
    //printf("oscill thread running\n");
    //oscillLooper();
    //printfAllThreadStat();
    rt_thread_mdelay(10);
  }
}
/**
 * @brief : 万用表更新线程
 * @param {void} *p
 * @return {*}
 */
void multiMeterThread(void *p)
{
  while (1)
  {
    /* code */
    //printf("multiMeter thread running\n");

    //MultiMeterValueUpdateLooper();
    rt_thread_mdelay(10);
  }
}
/**
 * @brief : 模块管理
 * @param {*}
 * @return {*}
 */
static void moduleManagement(uint8_t module, uint8_t state)
{
  switch (module)
  {
  case MODULE_KEYBOARD:
    if (state == DISCONNECTED)
    {
      V_goHome();
    }
    /* code */
    break;
  case MODULE_MULTIMETER:
    if (state == DISCONNECTED && getCurrentApp() == APP_MULTIMETER)
    {
      V_goHome();
    }

    /* code */
    break;
  case MODULE_OSCILL:
    if (state == DISCONNECTED && getCurrentApp() == APP_OSCILL)
    {
      V_goHome();
    }

    /* code */
    break;

  default:
    break;
  }
}
/**
 * @brief : 用于测量FPS、指示系统工作状态,每秒运行一次
 * @param {*}
 * @return {*}
 */
static void oneSecond2Cb(void *p)
{
  static rt_uint32_t total, used, max_used;

#ifdef SHOW_FPS
  printf("FPS:%d,touch:%d\n", Fps, touchFreashRate);
#endif

  Fps = 0;
  touchFreashRate = 0;
  trigLed(LED_GREEN);

#ifdef SHOW_HEAP_INFO
  rt_memory_info(&total, &used, &max_used);
  printf("mem:total:%ld,used:%ld,max:%ld\n", total, used, max_used);
#endif

  //moduleChecking();
}

#ifdef GUI_LVGL
static void lv_timer(void *p)
{
  lv_tick_inc(10);
}
#endif

/**
 * @brief : 系统初始化
 * @param {*}
 * @return {*}
 */
void sysInit()
{

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  delay_init(144);
  fileSystemInit();

#ifdef GUI_UCGUI
  GUI_Init();
#endif

#ifdef GUI_LVGL
  lv_init();
  hal_init();
#endif
  rt_system_timer_init();

  LED_Init();
  Touch_Init();
  //KEY_Init();
  //DSP_Init();
  Beeper_Init();
#ifdef MUTE
  beeperMute();
#endif

  // setModuleCheckingCb(moduleManagement);
}
/**
 * @brief : 线程及线程相关配件初始化,仅仅初始化，但不启动线程
 * @param {*}
 * @return {*}
 */
void threadInit()
{
  rt_err_t result;
  rt_thread_t settingPtr;
  int i = 0;

  // result = rt_thread_init(
  //     &touchScreenThread_ptr, "touchScreenThread", touchScreenThread, RT_NULL,
  //     &touchScreenThread_stack[0], sizeof(touchScreenThread_stack), 0, 500);
  // if (rt_thread_startup(&touchScreenThread_ptr) == RT_EOK && result == RT_EOK)
  // {
  //   printf("touchScreenThread created\n");
  // }
  // else
  // {
  //   printf("ERROR:touchScreenThread not created\n");
  // }

  // result = rt_thread_init(&buttonThread_ptr, "buttonThread", buttonThread,
  //                         RT_NULL, &buttonThread_stack[0],
  //                         sizeof(buttonThread_stack), 2, 300);
  // if (rt_thread_startup(&buttonThread_ptr) == RT_EOK && result == RT_EOK)
  // {
  //   printf("buttonThread created\n");
  // }
  // else
  // {
  //   printf("ERROR:buttonThread not created\n");
  // }
  //初始化tft线程
  result = rt_thread_init(&TFTThread_ptr, "TFTThread", tftUpdateThread, RT_NULL,
                          &TFTThread_stack[0], sizeof(TFTThread_stack), 0, 1000);
  //创建互斥锁
  if (rt_mutex_init(&lvglMutex, "lvglMutex,", RT_IPC_FLAG_PRIO) == RT_EOK)
  {
    printf("lvglMutex init done...\n");
  }
  else
  {
    printf("lvglMutex init failed...\n");
    while (1)
      ;
  }
  // //oscillThread
  // result = rt_thread_init(&oscillThread_ptr, "oscillThread", oscillThread,
  //                         RT_NULL, &oscillThread_stack[0],
  //                         sizeof(oscillThread_stack), 3, 1000);
  // printf("oscillThread created\n");

  // result = rt_thread_init(&multiMeterThread_ptr, "METERThread", multiMeterThread,
  //                         RT_NULL, &multiMeterThread_stack[0],
  //                         sizeof(multiMeterThread_stack), 2, 1000);
  // printf("multiMeterThread created\n");
}
/**
 * @brief :线程启动
 * @param {*}
 * @return {*}
 */
void threadStart()
{
  if (rt_thread_startup(&TFTThread_ptr) == RT_EOK)
  {
    printf("TFT thread created\n");
  }
  else
  {
    printf("TFT thread failed\n");
  }
}
/**
 * @brief :定时器启动
 * @param {*}
 * @return {*}
 */
void timerStart()
{
  //1秒定时器
  rt_timer_start(
      rt_timer_create("oneSecond2",
                      oneSecond2Cb,
                      NULL,
                      1000,
                      RT_TIMER_FLAG_HARD_TIMER | RT_TIMER_FLAG_PERIODIC));

#ifdef GUI_LVGL
  //lgvl时钟信号
  rt_timer_start(
      rt_timer_create("lvTimerBeat",
                      lv_timer,
                      NULL,
                      10,
                      RT_TIMER_FLAG_HARD_TIMER | RT_TIMER_FLAG_PERIODIC));
#endif
}
/**
 * @brief : 文件系统读测试（已通过测试）
 * @param {*}
 * @return {*}
 */
void testForFATFS()
{
  FIL fp;
  uint8_t buf[50];

  FRESULT res = f_open(&fp, "0:/testDir/test.txt", FA_READ);
  if (res != FR_OK)
  {
    printf("open error\n");
    return;
  }
  UINT br;
  res = f_read(&fp, buf, 50, &br);
  if (res != FR_OK)
  {
    printf("read error\n");
    return;
  }
  printf("FATFS string is '%.*s'\n", br, buf);
  f_close(&fp);

  //测试文件夹
  //mf_scan_files("0:/testDir");

  res = f_open(&fp, "0:/bootInfo.txt", FA_READ | FA_WRITE | FA_OPEN_ALWAYS);
  if (res != FR_OK)
  {
    printf("bootInfo.txt open error!\n");
    return;
  }
  else
  {
    printf("bootInfo.txt open done...\n");
  }

  res = f_read(&fp, buf, 20, &br);
  //第一次创建此文件
  if (br == 0)
  {
    printf("first time booting\n");
    strcpy(buf, "bootTime:1;");
    res = f_puts(buf, &fp);
    if (res != FR_OK)
    {
      printf("f_puts error!\n");
    }
  }
  //
  else
  {
    //f_gets(buf, sizeof(buf) / sizeof(uint8_t), &fp);
    f_lseek(&fp, 0);
    int bootTime;
    char bootTimeBuf[25];
    char *head;
    char *end;
    res = f_read(&fp, buf, 25, &br);
    if (res != FR_OK)
    {
      printf("read bootTime error!\n");
    }
    printf("%.*s \n", br, buf);
    //找出：后面的字符串
    head = strchr(buf, ':');
    if (head != NULL)
    {
      strncpy(bootTimeBuf, head + 1, 4);
      //找到尾部的;字符，并直接置0
      end = strchr(bootTimeBuf, ';');
      if (end != NULL)
      {
        *end = '\0';
        bootTime = atoi(bootTimeBuf);
        printf("boot time num:%d\n", bootTime);
        bootTime++;
        sprintf(bootTimeBuf, "bootTime:%d;", bootTime);
        f_lseek(&fp, 0);
        res = f_write(&fp, bootTimeBuf, strlen(bootTimeBuf), &br);
        if (res != FR_OK)
        {
          printf("writing boot time error!\n");
        }
      }
    }
  }

  f_close(&fp);
}
/**
 * @brief : LVGL文件系统读测试
 * @param {*}
 * @return {*}
 */
void testForLvglFS()
{
  lv_fs_file_t f;
  lv_fs_res_t res;
  res = lv_fs_open(&f, "0:/testDir/test.txt", LV_FS_MODE_RD);
  if (res != LV_FS_RES_OK)
  {
    printf("open error\n");
  }

  uint32_t read_num;
  uint8_t buf[30];
  res = lv_fs_read(&f, buf, 30, &read_num);
  if (res != LV_FS_RES_OK)
  {
    printf("read error\n");
  }
  else
  {
    printf("LVGL test string is  %.*s\n", read_num, buf);
  }

  lv_fs_close(&f);

  //测试读取文件夹
  lv_fs_dir_t dir;
  res = lv_fs_dir_open(&dir, "0:/testDir");
  if (res != LV_FS_RES_OK)
  {
    printf("lvgl open dir error\n");
    return;
  }
  else
  {
    printf("lvgl open dir done...\n");
  }

  char fn[10 * 2 + 1];
  while (1)
  {
    res = lv_fs_dir_read(&dir, fn);
    if (res != LV_FS_RES_OK)
    {
      printf("read dir error\n");
      return;
      break;
    }

    /*fn is empty, if not more files to read*/
    if (strlen(fn) == 0)
    {
      break;
    }

    printf("%s\n", fn);
  }

  lv_fs_dir_close(&dir);
}
void loadFont()
{
  updata_fontx(0, 0, 0, "0:/font/myFont.bin", 4);
}
/**
 * @brief : main函数
 * @param {*}
 * @return {*}
 */
void main(void)
{
  sysInit();
  testForFATFS();
  testForLvglFS();
  //loadFont();

  homePageInit(0);
  //线程和定时器的初始化一定要放在最后，否则会出错
  threadInit();

  threadStart();

  timerStart();
}

/**
 * @brief : 启动示波器线程
 * @param {*}
 * @return {*}
 */
void startOscillThread()
{
  rt_thread_startup(&oscillThread_ptr);
  printf("oscillThread started\n");
}
/**
 * @brief : 删除示波器应用线程，再次启动无需重新初始化
 * @param {*}
 * @return {*}
 */
void killOscillThread()
{
  closeOscil();
  rt_thread_delete(&oscillThread_ptr);
  printf("OscillThread deleted\n");
}
/**
 * @brief : 启动万用表线程
 * @param {*}
 * @return {*}
 */
void startMultiMeterThread()
{
  rt_thread_startup(&multiMeterThread_ptr);
  printf("multiMeterThread started\n");
}
/**
 * @brief : 删除万用表线程，再次启动无需重新初始化
 * @param {*}
 * @return {*}
 */
void killMultiMeterThread()
{
  closeMultiMeter();
  rt_thread_delete(&multiMeterThread_ptr);
  printf("multiMeterThread deleted\n");
}
